#pragma once

#include <JavaScriptCore/JavaScript.h>

class CWebkitView;
class APIString
{
public:

	APIString(const char* string) : m_string(string ? JSStringCreateWithUTF8CString(string) : nullptr){}
	~APIString() { if (m_string) JSStringRelease(m_string); }
	operator JSStringRef() { return m_string; }
private:
	JSStringRef m_string;
};

class CJSAPI
{
public:
	CJSAPI(JSContextRef context) :m_context(context) {}
	static CString JSValueToString(JSContextRef ctx, JSValueRef value);

	__forceinline CString& error() { return errmsg; }
	bool addActiveX(bool add);
	__forceinline JSValueRef callFunction(LPCSTR funcName, size_t argc, const JSValueRef arguments[],
		JSObjectRef thisObject = nullptr, JSValueRef* exception = nullptr)
	{
		return callFunction(getFunction(funcName, thisObject), argc, arguments, thisObject, exception);
	}
	JSObjectRef SetHook(LPCSTR funcName, JSObjectCallAsFunctionCallback funcHook, JSObjectRef thisObject = nullptr);
#ifdef _WEBKIT_NEW
	bool installMutationObserver(CWebkitView *caller);
	bool fastLogin(LPCSTR script);
	bool GetWinSize(CSize &winSize);
	bool GetRotateRate(LPCWSTR DragWrapName, LPCWSTR DragBtnName, double &rate);
#endif
protected:
	bool checkNullObj(JSObjectRef &thisObject);
	JSValueRef evaluateScript(LPCSTR script, JSObjectRef thisObject = nullptr);
	JSObjectRef newInstance(LPCSTR className, size_t argc, const JSValueRef arguments[]);
	JSObjectRef newFunction(LPCSTR funcName, JSObjectCallAsFunctionCallback funcBody, JSObjectRef thisObject = nullptr);
	JSValueRef getProperty(LPCSTR propNames, JSObjectRef thisObject = nullptr);
	bool setProperty(LPCSTR propNames, JSValueRef value, JSPropertyAttributes attributes, JSObjectRef thisObject = nullptr);
	JSObjectRef getFunction(LPCSTR funcName, JSObjectRef thisObject = nullptr);
	JSValueRef callFunction(JSObjectRef func, size_t argc, const JSValueRef arguments[],
		JSObjectRef thisObject = nullptr, JSValueRef* exception = nullptr);
	__forceinline CString JSValueToString(JSValueRef value) const { return CJSAPI::JSValueToString(m_context, value); }
	bool checkException(JSValueRef exception, JSValueRef retValue, CString &msg) const;

	CString errmsg;
	JSContextRef m_context;
};
